package com.molyfun.parents.utils;

import com.molyfun.parents.utils.security.BASE64Encoder;
import com.molyfun.parents.utils.security.BusinessException;
import com.molyfun.parents.utils.security.coder.DESCoder;
import com.molyfun.parents.utils.security.coder.HmacCoder;
import com.molyfun.parents.utils.security.coder.MDCoder;
import com.molyfun.parents.utils.security.coder.PBEWithMD5AndDESCoder;
import com.molyfun.parents.utils.security.coder.RSACoder;
import com.molyfun.parents.utils.security.coder.SHACoder;

import junit.framework.Assert;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;


/**
 * 数据加密辅助类(默认编码UTF-8)
 * 
 */
public final class SecurityUtil {
	private SecurityUtil() {
	}


//	public static final ResourceBundle SECURITY = ResourceBundle.getBundle("config/security");

	/**
	 * 默认算法密钥
	 */
	private static final byte[] ENCRYPT_KEY = { -81, 0, 105, 7, -32, 26, -49, 88 };

	public static final String CHARSET = "UTF-8";

	private static final String PBE_PASSWORD = "Mx.r6polY2=+#+X13?)`~1T/<>";

	
	/**
	 * BASE64解码
	 * 
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static final byte[] decryptBASE64(String key) throws BusinessException {
		try {
			return new BASE64Encoder().decode(key);
		} catch (Exception e) {
			throw new BusinessException("解密错误，错误信息：", e);
		}
	}

	/**
	 * BASE64编码
	 * 
	 * @param key
	 * @return
	 * @throws Exception
	 */
	public static final String encryptBASE64(byte[] key) throws BusinessException {
		try {
			return new BASE64Encoder().encode(key);
		} catch (Exception e) {
			throw new BusinessException("加密错误，错误信息：", e);
		}
	}

	/**
	 * 数据解密，算法（DES）
	 * 
	 * @param cryptData 加密数据
	 * @return 解密后的数据
	 */
	public static final String decryptDes(String cryptData) throws BusinessException {
		return decryptDes(cryptData, ENCRYPT_KEY);
	}

	/**
	 * 数据加密，算法（DES）
	 * 
	 * @param data 要进行加密的数据
	 * @return 加密后的数据
	 * @throws UnsupportedEncodingException 
	 * @throws NoSuchAlgorithmException 
	 */
	public static final String encryptDes(String data) throws UnsupportedEncodingException, NoSuchAlgorithmException ,BusinessException {
		return encryptDes(data, ENCRYPT_KEY);
	}

	/**
	 * 基于MD5算法的单向加密
	 * 
	 * @param strSrc 明文
	 * @return 返回密文
	 */
	public static final String encryptMd5(String strSrc) throws BusinessException {
		String outString = null;
		try {
			outString = encryptBASE64(MDCoder.encodeMD5(strSrc.getBytes(CHARSET)));
		} catch (Exception e) {
			throw new BusinessException("加密错误，错误信息：", e);
		}
		return outString;
	}

	/**
	 * SHA加密
	 * 
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public static final String encryptSHA(String data) throws BusinessException {
		try {
			return encryptBASE64(SHACoder.encodeSHA256(data.getBytes(CHARSET)));
		} catch (Exception e) {
			throw new BusinessException("加密错误，错误信息：", e);
		}
	}

	/**
	 * HMAC加密
	 * 
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public static final String encryptHMAC(String data) throws BusinessException {
		return encryptHMAC(data, ENCRYPT_KEY);
	}

	/**
	 * 数据解密，算法（DES）
	 * 
	 * @param cryptData 加密数据
	 * @return 解密后的数据
	 */
	public static final String decryptDes(String cryptData, byte[] key) throws BusinessException {
		String decryptedData = null;
		try {
			// 把字符串解码为字节数组，并解密
			decryptedData = new String(DESCoder.decrypt(decryptBASE64(cryptData), key));
		} catch (Exception e) {
			throw new BusinessException("解密错误，错误信息：", e);
		}
		return decryptedData;
	}

	/**
	 * 数据加密，算法（DES）
	 * 
	 * @param data 要进行加密的数据
	 * @return 加密后的数据
	 */
	public static final String encryptDes(String data, byte[] key) throws BusinessException {
		String encryptedData = null;
		try {
			// 加密，并把字节数组编码成字符串
			encryptedData = encryptBASE64(DESCoder.encrypt(data.getBytes(), key));
		} catch (Exception e) {
			throw new BusinessException("加密错误，错误信息：", e);
		}
		return encryptedData;
	}

	/**
	 * HMAC加密
	 * 
	 * @param data
	 * @return
	 * @throws Exception
	 */
	public static final String encryptHMAC(String data, byte[] key) throws BusinessException {
		try {
			return encryptBASE64(HmacCoder.encodeHmacSHA512(data.getBytes(CHARSET), key));
		} catch (Exception e) {
			throw new BusinessException("加密错误，错误信息：", e);
		}
	}
	
	/**
	 * 数据加密，算法（PBE）
	 * 
	 * @param data 要进行加密的数据
	 */
	public static final String encryptPBE(String data) throws BusinessException {
		return 	PBEWithMD5AndDESCoder.encrypt(data, PBE_PASSWORD, PBEWithMD5AndDESCoder.getStaticSalt());
	}


	/**
	 * 数据加密，算法（PBE）
	 * 
	 * @param data 要进行解密的数据
	 */
	public static final String decryptPBE(String ciphertext) throws BusinessException {
		return 	PBEWithMD5AndDESCoder.decrypt(ciphertext, PBE_PASSWORD, PBEWithMD5AndDESCoder.getStaticSalt());
	}

	/**
	 * RSA签名
	 * 
	 * @param data 原数据
	 * @return
	 */
	public static final String signRSA(String data, String privateKey) throws BusinessException {
		try {
			return encryptBASE64(RSACoder.sign(data.getBytes(CHARSET), decryptBASE64(privateKey)));
		} catch (Exception e) {
			throw new BusinessException("签名错误，错误信息：", e);
		}
	}

	/**
	 * RSA验签
	 * 
	 * @param data 原数据
	 * @return
	 */
	public static final boolean verifyRSA(String data, String publicKey, String sign) throws BusinessException {
		try {
			return RSACoder.verify(data.getBytes(CHARSET), decryptBASE64(publicKey), decryptBASE64(sign));
		} catch (Exception e) {
			throw new BusinessException("验签错误，错误信息：", e);
		}
	}

	/**
	 * 数据加密，算法（RSA）
	 * 
	 * @param data 数据
	 * @return 加密后的数据
	 */
	public static final String encryptRSAPrivate(String data, String privateKey) throws BusinessException {
		try {
			return encryptBASE64(RSACoder.encryptByPrivateKey(data.getBytes(CHARSET), decryptBASE64(privateKey)));
		} catch (Exception e) {
			throw new BusinessException("解密错误，错误信息：", e);
		}
	}

	/**
	 * 数据加密，算法（RSA）
	 * 
	 * @param data 数据
	 * @return 加密后的数据
	 */
	public static final String encryptRSAPublic(String data, String publicKey) throws BusinessException {
		try {
			return encryptBASE64(RSACoder.encryptByPublicKey(data.getBytes(CHARSET), decryptBASE64(publicKey)));
		} catch (Exception e) {
			throw new BusinessException("解密错误，错误信息：", e);
		}
	}


	/**
	 * 数据解密，算法（RSA）
	 * 
	 * @param cryptData 加密数据
	 * @return 解密后的数据
	 */
	public static final String decryptRSAPublic(String cryptData, String publicKey) throws BusinessException{
		try {
			// 把字符串解码为字节数组，并解密
			return new String(RSACoder.decryptByPublicKey(decryptBASE64(cryptData), decryptBASE64(publicKey)));
		} catch (Exception e) {
			throw new BusinessException("解密错误，错误信息：", e);
		}
	}

	/**
	 * 数据解密，算法（RSA）
	 * 
	 * @param cryptData 加密数据
	 * @return 解密后的数据
	 */
	public static final String decryptRSAPrivate(String cryptData, String privateKey) throws BusinessException{
		try {
			// 把字符串解码为字节数组，并解密
			return new String(RSACoder.decryptByPrivateKey(decryptBASE64(cryptData), decryptBASE64(privateKey)));
		} catch (Exception e) {
			throw new BusinessException("解密错误，错误信息：", e);
		}
	}



//	/**
//	 * 检验客户端提交数据
//	 * @return
//	 */
//	public static String verifyEncryptDataByRSA(HttpServletRequest request)
//	{
//		try {
//			String body = IOUtils.toString(request.getInputStream(),"UTF-8");
//			String data = decryptRSAPrivate(body, SECURITY.getString("server.private_key"));
//			Map<String,String> headers = WebUtil.getHeadersInfo(request);
//			String sign = headers.get("sign");
//			boolean result = verifyRSA(data, SECURITY.getString("client.public_key"), sign);
//			Assert.isTrue(result, "签名错误");
//			return data;
//		} catch (Exception e) {
//			throw new BusinessException("数据异常");
//		}
//	}


	public static String serverPublicKey = "mig6maQgcsGgsi2TdqebaquaaUgnadcb9qkb7qcVgAN0dlIe7MAIIVG/UNsdLHYQafIHvYIvZPpH0iqVMIMFE+i7PaRNjBrAR8Qwu2I24JN4glZCSun5z4fsDy3eyLtTMXhHwGWUP9tQ17OUU/la9fbbNnDwamda1wn+ZJCQCn6UXWTKsbJBD79Pl/WHsitKSmPVndW+vslZvU4dWMidaqab";
	//
	public static String clientPrivateKey = "miic47ibadanb7AG8A9gZMQbaqefaascaCaM77j3a7eaaEgbal4zFh4hnrmPQyl58kLq63hRaU9NwcZhQTKHK+yp98sYeqzXMQ2ypKLx2vSj7kWzRJuyFJpeHgOxQiHaMZvUHQ0yDbIocPCMLNHtzjhH4e58bemRqi7w2jC3hiNuVUyG7ZyHus8BFMUc2Y9D/uyOifVfGghmBTMGqsQL07dHA6Y2a7mbaaec7yabxmEHflR8o9zz1zLANLtyrOdsCd2g9OIyjsKnrNFiAOANo9qSvUYiiVWJ2AmB9qe5HAmTg1qkxEFLlywhbzgpTIG15MMdWoyENSRRXAjpkMWM4y+swNsphzQ6cu6ko2v25k7vq+lYDyllbas1XbQXgDdxCou3r4/LO7c4MBfM5qjbaouK5A4BLtrv3oUDGk+BnDX2KjRzrAY5vgzt+W+mKNfnp3D4hbn3oJHppeae6BA0hCgkSJSvdOwOBIV7mKIInYQcqqdmP0uOHf5X+TfxlE52wGJYF55bsiO2m37cGQ/hfH40bGE+/B2X2lGSznYjbDGURZayJ6n2+5RjR2GKMXXkHnGhaAeaR6sFbysKKw/wGqZLronjv+Zk0+mHzSK1qzDacO9DXYq2D8MfpphkFehWlETdyLynq+tYVqzC9lMmxa9BilyYnqjaxUAvy2tFhcrxEUVJXx3Djx3s63BeV1q3iXG2Zu6q44UhdCCauXFn7Ew4umRTYX+7lZ1Uv3bjaP3OVreA2Zc7aMjamQma65K2DBxyqqMBU0l6vQq7rCK8eXD5E9gEARuCiFLXLaCqvAExqJH8+F6a36+PiUq7zJ5SF4Ka7xwev33ega==";

	public static void main(String[] args) throws Exception  {
//				System.out.println(encryptDes("SHJR"));
//				System.out.println(decryptDes("INzvw/3Qc4q="));
				
//				System.out.println(encryptPBE("111111"));
//				System.out.println(decryptPBE("85f0463874760aab"));
				
		//		System.out.println(encryptMd5("SHJR"));
		//		System.out.println(encryptSHA("1"));
		//服务器
		//				Map<String, Object> key = RSACoder.initKey();
		//				String privateKey = encryptBASE64(RSACoder.getPrivateKey(key));
		//				String publicKey = encryptBASE64(RSACoder.getPublicKey(key));
		//				System.out.println(privateKey);
		//				System.out.println(publicKey);
		//
		//		//客户端
		//				Map<String, Object> key1 = RSACoder.initKey();
		//				String privateKey1 = encryptBASE64(RSACoder.getPrivateKey(key1));
		//				String publicKey1 = encryptBASE64(RSACoder.getPublicKey(key1));
		//				System.out.println(privateKey1);
		//				System.out.println(publicKey1);
		String serverPrivateKey = "miic5aibadanb7AG8A9gZMQbaqefaascaCiM77j5a7eaaEgbalA1tgmmKMsdcsOPCH/0fio+LPqawOJxONxTm+Km8dDcPcC0U9dmdxeCvgtwhrzrKNJSTfQyLS2zqRVBQvk48Mr9Zp6dI5J1HH0ojprGdl00YIciueheS4yaMmbFyTXSS2syR/0LH5VigSw5clmL/GJi8oXyPpAQpHVviLRx8QpHa7mbaaec7yaOItQsmPVu36VBoVGVOBGDW5AXoiS/rp/4ocidZcKsf7mlJfinyvs4fdUM0SlpV6EP/QRcq2djx4XrtRAqiMMc3LSKeqcmHtWqxO2LeHEB4h0yPcVf+uz/rPA+p305AONTPYqqFpg1jmDYs4ufKhRRuwwZSRbtDfm8D4lwn0AR7qjbapN6OQ/sqI1dejzPIFWjPmY3yX9A0+Y1KTxI+ZP76C3VAlA96YcvHw3ZLaA0XRP+Q6XA80S4L64vtKsI9x6ht0IcqqcXMNyU3yvzTRFJO7IHLBW2DR7X4vBlrtG0BmjPF9r0UqzreUOrx3id0xOrDTnUBlKN1Xo4VfxqQcia+sCeB8yraAeaYeFjkOLUfA8KpYhthoTVsCQK1xOnWIL1fLlxXXHPLR2E+YPAndGpcJcvKSiOEGC7O6ZnXv2gGXHwP8wvi1RHrMjbaif8kwovx3usY6xHh7RP2s+7+9rC4tqTHpn8iO92CegSE9GBVnK1fEfGm93kdUbmrjuVSj6UW5uIn6i0LG33Uhecqqc3A75c5UWwraCFWt1UWObxfbzafok1Fsws6jN3wG9QJk2q5bAFr8BAMIlzk13puxyeo3jRCESo7e2JF6aKpG05";

//		String serverPublicKey = "mig6maQgcsGgsi2TdqebaquaaUgnadcb9qkb7qcVgAN0dlIe7MAIIVG/UNsdLHYQafIHvYIvZPpH0iqVMIMFE+i7PaRNjBrAR8Qwu2I24JN4glZCSun5z4fsDy3eyLtTMXhHwGWUP9tQ17OUU/la9fbbNnDwamda1wn+ZJCQCn6UXWTKsbJBD79Pl/WHsitKSmPVndW+vslZvU4dWMidaqab";
////
//		String clientPrivateKey = "miic47ibadanb7AG8A9gZMQbaqefaascaCaM77j3a7eaaEgbal4zFh4hnrmPQyl58kLq63hRaU9NwcZhQTKHK+yp98sYeqzXMQ2ypKLx2vSj7kWzRJuyFJpeHgOxQiHaMZvUHQ0yDbIocPCMLNHtzjhH4e58bemRqi7w2jC3hiNuVUyG7ZyHus8BFMUc2Y9D/uyOifVfGghmBTMGqsQL07dHA6Y2a7mbaaec7yabxmEHflR8o9zz1zLANLtyrOdsCd2g9OIyjsKnrNFiAOANo9qSvUYiiVWJ2AmB9qe5HAmTg1qkxEFLlywhbzgpTIG15MMdWoyENSRRXAjpkMWM4y+swNsphzQ6cu6ko2v25k7vq+lYDyllbas1XbQXgDdxCou3r4/LO7c4MBfM5qjbaouK5A4BLtrv3oUDGk+BnDX2KjRzrAY5vgzt+W+mKNfnp3D4hbn3oJHppeae6BA0hCgkSJSvdOwOBIV7mKIInYQcqqdmP0uOHf5X+TfxlE52wGJYF55bsiO2m37cGQ/hfH40bGE+/B2X2lGSznYjbDGURZayJ6n2+5RjR2GKMXXkHnGhaAeaR6sFbysKKw/wGqZLronjv+Zk0+mHzSK1qzDacO9DXYq2D8MfpphkFehWlETdyLynq+tYVqzC9lMmxa9BilyYnqjaxUAvy2tFhcrxEUVJXx3Djx3s63BeV1q3iXG2Zu6q44UhdCCauXFn7Ew4umRTYX+7lZ1Uv3bjaP3OVreA2Zc7aMjamQma65K2DBxyqqMBU0l6vQq7rCK8eXD5E9gEARuCiFLXLaCqvAExqJH8+F6a36+PiUq7zJ5SF4Ka7xwev33ega==";
		String clientPublicKey = "mig6maQgcsGgsi2TdqebaquaaUgnadcb9qkb7qcTw1rTrPutmZgcTEsHQhTbZqoiIv7LrZnXGXLCdUEuLbeg5YngSdXHRSR49ycKC42vgk2tNkNIBZckMmpv5kZiSjM2d7IVIlY1QSsrWTrhEqrdnucifCOzDbOmvo5gkEpwkReEz13oaC/iF/Rgm9b5r188Pj4YkAeJlUUaWVh/gMidaqab";
//		//phone=13777777777&invitecode=h5636&username=我的哥&password=111111&imgurl=
		String sign = signRSA("phone=18611429611&password=111111&username=liuchao&invitecode=8JAQUP7", clientPrivateKey);
		System.out.println(sign);
		String encrypt = encryptRSAPublic("phone=18611429611&password=111111&username=liuchao&invitecode=8JAQUP7", serverPublicKey);
		System.out.println("encrypt--->" + encrypt);
		//		String org = decryptRSAPrivate(encrypt, serverPrivateKey);
		//		System.out.println(org);
		//		System.out.println(verifyRSA(org, clientPublicKey, sign));

		// System.out.println("-------列出加密服务提供者-----");
		// Provider[] pro = Security.getProviders();
		// for (Provider p : pro) {
		// System.out.println("Provider:" + p.getName() + " - version:" +
		// p.getVersion());
		// System.out.println(p.getInfo());
		// }
		// System.out.println("");
		// System.out.println("-------列出系统支持的消息摘要算法：");
		// for (String s : Security.getAlgorithms("MessageDigest")) {
		// System.out.println(s);
		// }
		// System.out.println("-------列出系统支持的生成公钥和私钥对的算法：");
		// for (String s : Security.getAlgorithms("KeyPairGenerator")) {
		// System.out.println(s);
		// }
	}

	public static String checkSignature(Map mapPram) {
		String[] arr = new String[3];
		int k = 0;
		String signature = "";
		Set<String> set = mapPram.keySet();
		for (String s:set) {
						System.out.println("mapPram"+mapPram.get(s));
			if("nonce".equals(s) || "timestamp".equals(s))
			{
				arr[k] =  (String) mapPram.get(s);
				k++;
			}

			if("signature".equals(s))
			{
				signature = (String) mapPram.get(s);
			}
		}
		boolean flag = true;
		arr[2] = "ea21ab6d95e14559a1be79620dbb6737";
		for(String obj : arr)
		{
			if(obj == null)
			{
				flag = false;
				break;
			}
		}
		if(arr == null || !flag)
		{
//			return false;
			return "";
		}
		// 将token、timestamp、nonce三个参数进行字典序排序
		Arrays.sort(arr);

		StringBuilder content = new StringBuilder();
		for (int i = 0; i < arr.length; i++) {
			content.append(arr[i]);
			System.out.println("mapPram"+content.toString()+"content");
		}

		MessageDigest md = null;
		String tmpStr = null;

		try {
			md = MessageDigest.getInstance("SHA-1");
			// 将三个参数字符串拼接成一个字符串进行sha1加密
			byte[] digest = md.digest(content.toString().getBytes());
			tmpStr = byteToStr(digest);
			System.out.println("mapPram"+tmpStr+"tmpStr");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}

		content = null;
		// 将sha1加密后的字符串可与signature对比，标识该请求来源于微信
//		return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;
		/*if(tmpStr.equals(signature.toUpperCase())) {
			return tmpStr;
		}else {
			return "";
		}*/
		return tmpStr;
	}
	private static String byteToStr(byte[] byteArray) {
		String strDigest = "";
		for (int i = 0; i < byteArray.length; i++) {
			strDigest += byteToHexStr(byteArray[i]);
		}
		return strDigest;
	}
	private static String byteToHexStr(byte mByte) {

		char[] Digit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
		char[] tempArr = new char[2];
		tempArr[0] = Digit[(mByte >>> 4) & 0X0F];
		tempArr[1] = Digit[mByte & 0X0F];

		String s = new String(tempArr);
		return s;
	}

}
